package com.example.hbase_server.service;

/*
    Author: Julian Droid
*/

import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

@Service
public class FuncWrapper {

    private static class Command {
        String command;
        Object[] args;
        public Command(String command, Object... args){
            this.command = command;
            this.args = args;
        }
    }

    Func func = null;
    static Object callLocker = new Object();

    Command inputCommand = null;
    Object returnValue = null;

    public void init() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                func = new Func();
                Method[] _methods = Func.class.getMethods();
                HashMap<String, Method> methods = new HashMap<String, Method>();
                for(Method method : _methods) {
                    String name = method.getName();
                    Method oldMethod = methods.get(name);
                    if(oldMethod != null) System.err.printf("Warning: Methods with the same name '%s' are not suppored yet\n", name);
                    methods.put(name, method);
                }

                while (true) {
                    synchronized (callLocker) {
                        try {
                            if(inputCommand == null) callLocker.wait();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        // invoke
                        String functionName = inputCommand.command;
                        Method method = methods.get(functionName);
                        if(method != null){
                            try {
                                returnValue = null;
                                returnValue = method.invoke(func, inputCommand.args);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }else{
                            System.err.printf("Error: Cannot find method with name %s\n", functionName);
                        }
                        inputCommand = null;
                        callLocker.notify();
                    }
                }
            }
        }).start();
    }

    public Object call(String functionName, Object... args){
        inputCommand = new Command(functionName, args);
        // multiple calls from different threads
        synchronized (callLocker) {
            callLocker.notify();

            try {
                callLocker.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return returnValue;
    }
}
/*居子平真叼*/
